package com.fxu.framework.core.util;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.map.MapBuilder;
import cn.hutool.core.util.StrUtil;
import com.fxu.framework.biz.base.Param;
import com.fxu.framework.core.sql.SEntity;
import com.fxu.framework.core.sql.SType;
import com.fxu.framework.core.sql.SValue;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import static com.fxu.framework.biz.base.Param.getQueryType;

/**
 * Map增强相关工具类
 * @author fangxu
 * @see cn.hutool.core.map.MapUtil
 * @version 1.0.0
 */
public class MapUtil extends cn.hutool.core.map.MapUtil {

	/**
	 * 将传入参数依次以key,value放入数组
	 * @param k key
	 * @param v value
	 * @return MapBuilder
	 */
	public static MapBuilder<String, Object> put(String k, Object v) {
		if (null == k) {
			return builder(new HashMap<>());
		}
		return builder(new HashMap<String, Object>()).put(k, v);
	}

	/**
	 * 从所有属性中获取属性值，且删除key内容
	 * @param map Map
	 * @param key 关键值
	 * @param others 键值集合
	 */
	@SuppressWarnings("varargs")
	public static void remove(Map<String, Object> map, String key, String ...others) {
		for (String other : others) {
			map.remove(key + other);
		}
	}

	/**
	 * 从所有属性中获取属性值，且删除key内容
	 * @param map Map
	 * @param key 键值
	 * @return 对应的值
	 */
	public static <SE extends SEntity<SE>> SValue getAndClear(Map<String, Object> map, String key) {
		for (String vueLink : Param.getVueLinks()) {
			if (map.containsKey(key + vueLink)) {
				String sKey = key + vueLink;
				SType sType = getQueryType(vueLink);
				String value = getStr(map, sKey);
				map.remove(sKey);
				return value == null ? null : new SValue(sType, null, value);
			}
		}
		return null;
	}

	/**
	 * 从所有属性中获取属性值，且删除key内容
	 * @param map Map
	 * @param keys 键值集合
	 * @return 对应的值
	 */
	@SuppressWarnings("varargs")
	public static String getAndRemove(Map<String, Object> map, String ...keys) {
		String value = null;
		for (String key : keys) {
			if (StrUtil.isEmpty(value)) {
				value = getStr(map, key, value);
			}
			map.remove(key);
		}
		return value;
	}

	/**
	 * 获取Map指定key的值，并转换为Bool
	 * @param map Map
	 * @param key 键
	 * @param defVal 默认值
	 * @return 值
	 * @since 4.0.6
	 */
	public static BigDecimal getDecimal(Map<?, ?> map, Object key, BigDecimal defVal) {
		return get(map, key, BigDecimal.class, defVal);
	}

	/**
	 * 获取Map指定key的值，并转换为字符串
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static String getStrNotEmpty(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, String.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为Integer
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static Integer getIntNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Integer.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为Double
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static Double getDoubleNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Double.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为Float
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static Float getFloatNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Float.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为Short
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static Short getShortNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Short.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为Bool
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static Boolean getBoolNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Boolean.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为Character
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static Character getCharNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Character.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为Long
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.0.6
	 */
	public static Long getLongNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Long.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为{@link Date}
	 * 
	 * @param map Map
	 * @param key 键
	 * @return 值
	 * @since 4.1.2
	 */
	public static Date getDateNotNull(Map<?, ?> map, Object key) {
		return getNotEmpty(map, key, Date.class);
	}
	
	/**
	 * 获取Map指定key的值，并转换为指定类型
	 * 
	 * @param <T> 目标值类型
	 * @param map Map
	 * @param key 键
	 * @param type 值类型
	 * @return 值
	 * @since 4.0.6
	 */
	public static <T> T getNotEmpty(Map<?, ?> map, Object key, Class<T> type) {
		if (null == map || null == map.get(key)) {
			throw new RuntimeException(StrUtil.format("map={}中的key={}不能为空", map, key));
		}
		return Convert.convert(type, map.get(key));
	}

}